package cl.foursoft.eee.dao.implementation.postgresql;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import cl.foursoft.eee.dao.facade.FacadeSensor;
import cl.foursoft.eee.dao.implementation.DBBase;
import cl.foursoft.eee.dao.interfaces.IMedicion;
import cl.foursoft.eee.dao.transferObject.MedicionTO;
import cl.foursoft.eee.dao.transferObject.TipoMedicionConsumoSensorTO;
import cl.foursoft.eee.dao.transferObject.VistaParaGestionTO;
import cl.foursoft.eee.util.CalculosUtil;
import cl.foursoft.eee.util.UtilLog;

public class MedicionDB extends DBBase implements IMedicion {
	
	public MedicionDB(Connection c){
		this.conn = c;
	}

	public List<MedicionTO> obtenerMedicionEdificioTipoConsumo(int idEdificio, String idMedicion) {
		List<MedicionTO> resp = null;
		ResultSet rs = null;
		PreparedStatement pstmt = null;
		
		String query = "SELECT m.fecha_hora, m.valor_medicion, m.id_sensor, m.id_consumo, m.id_medicion " +
						"FROM medicion_sensor_test m "+
						"INNER JOIN  sensor s on s.id_sensor = m.id_sensor "+
						"WHERE  m.id_medicion = ? and  s.id_edificio = ?";
		
		try {
			
			pstmt = this.conn.prepareStatement(query);
			
			pstmt.setString(1, idMedicion);
			pstmt.setInt(2, idEdificio);
			rs = pstmt.executeQuery();
			
			resp = new ArrayList<MedicionTO>();
			while(rs.next()){
				MedicionTO m = new MedicionTO();
				
				m.setFechaMedicion(rs.getTimestamp(1));
				m.setMedicion(rs.getFloat(2));
				
				m.setIdSensor(rs.getString(3));
				m.setIdTipoConsumo(rs.getString(4));
				m.setIdTipoMedicion(rs.getString(5));
				
				resp.add(m);
			}
			
			rs.close(); 
			pstmt.close();
		} catch (Exception e) {
			UtilLog.registrar(e);
		}finally{
			if(pstmt!=null){
				try {
					if(rs!=null)
						rs.close();
					pstmt.close();
				} catch (SQLException sqle) {
					UtilLog.registrar(sqle);
				}
			}
		}
		
		
		return resp;
	}
	@Override
	public List<MedicionTO> obtenerMedidasSensor(int idEdificio, String idConsumo, String idSensor) {
		List<MedicionTO> resp = null;
		ResultSet rs = null;
		PreparedStatement pstmt = null;
		
		String query = "SELECT m.fecha_hora, m.valor_medicion, m.id_sensor, m.id_consumo, m.id_medicion " +
		"FROM medicion_sensor_test m "+
		"INNER JOIN  sensor s on s.id_sensor = m.id_sensor "+
		"WHERE  m.id_medicion = ? and  s.id_edificio = ?";
		
		try {
			
			pstmt = this.conn.prepareStatement(query);
			
			pstmt.setString(1, idConsumo);
			pstmt.setInt(2, idEdificio);
			rs = pstmt.executeQuery();
			
			resp = new ArrayList<MedicionTO>();
			while(rs.next()){
				MedicionTO m = new MedicionTO();
				
				m.setFechaMedicion(rs.getTimestamp(1));
				m.setMedicion(rs.getFloat(2));
				
				m.setIdSensor(rs.getString(3));
				m.setIdTipoConsumo(rs.getString(4));
				m.setIdTipoMedicion(rs.getString(5));
				
				resp.add(m);
			}
			
			rs.close(); 
			pstmt.close();
		} catch (Exception e) {
			UtilLog.registrar(e);
		}finally{
			if(pstmt!=null){
				try {
					if(rs!=null)
						rs.close();
					pstmt.close();
				} catch (SQLException sqle) {
					UtilLog.registrar(sqle);
				}
			}
		}
		
		
		return resp;
	}

	@Override
	public List<MedicionTO> obtenerMedidasPiso(int piso, String idConsumo) {
		List<MedicionTO> resp = null;
		ResultSet rs = null;
		PreparedStatement pstmt = null;
		
		String query = "";
		
		try {
			
			pstmt = this.conn.prepareStatement(query);
			
			rs = pstmt.executeQuery();
			resp = new ArrayList<MedicionTO>();
			while(rs.next()){
				MedicionTO m = null;
				
				resp.add(m);
			}
			
			rs.close(); 
			pstmt.close();
		} catch (Exception e) {
			UtilLog.registrar(e);
		}finally{
			if(pstmt!=null){
				try {
					if(rs!=null)
						rs.close();
					pstmt.close();
				} catch (SQLException sqle) {
					UtilLog.registrar(sqle);
				}
			}
		}
		 
		
		return resp;
	}

	@Override
	public List<MedicionTO> obtenerMedidasEdificio(int idSensor, String idConsumo) {
		List<MedicionTO> resp = null;
		ResultSet rs = null;
		PreparedStatement pstmt = null;
		
		String query = "";
		
		try {
			
			pstmt = this.conn.prepareStatement(query);
			
			rs = pstmt.executeQuery();
			resp = new ArrayList<MedicionTO>();
			while(rs.next()){
				MedicionTO m = null;
				
				resp.add(m);
			}
			
			rs.close(); 
			pstmt.close();
		} catch (Exception e) {
			UtilLog.registrar(e);
		}finally{
			if(pstmt!=null){
				try {
					if(rs!=null)
						rs.close();
					pstmt.close();
				} catch (SQLException sqle) {
					UtilLog.registrar(sqle);
				}
			}
		}
		 
		
		return resp;
	}

	@Override
	public List<MedicionTO> obtenerMedidasZona(int zona, String idConsumo) {
		List<MedicionTO> resp = null;
		ResultSet rs = null;
		PreparedStatement pstmt = null;
		
		String query = "";
		
		try {
			
			pstmt = this.conn.prepareStatement(query);
			
			rs = pstmt.executeQuery();
			resp = new ArrayList<MedicionTO>();
			while(rs.next()){
				MedicionTO m = null;
				
				resp.add(m);
			}
			
			rs.close(); 
			pstmt.close();
		} catch (Exception e) {
			UtilLog.registrar(e);
		}finally{
			if(pstmt!=null){
				try {
					if(rs!=null)
						rs.close();
					pstmt.close();
				} catch (SQLException sqle) {
					UtilLog.registrar(sqle);
				}
			}
		}
		 
		
		return resp;
	}

	@Override
	public double totalMedicionMes(String idMedicion, int idEdificio) {
		double resp = 0;
		PreparedStatement pstmt = null;
		String query = "SELECT CONSUMO_MEDICION_MES( ? , ? );";
		ResultSet rs = null;
		try {
			pstmt = this.conn.prepareStatement(query);
			
			pstmt.setString(1, idMedicion);
			pstmt.setInt(2, idEdificio);
			
			
			rs = pstmt.executeQuery();
			if(rs.next())
				resp = rs.getDouble(1);
			
			
			resp = (resp>0) ? resp : 0;
			
			rs.close();
			pstmt.close();
			
		}
		catch(SQLException esql){
			UtilLog.registrar(esql);
		}
		catch (Exception e) {
			UtilLog.registrar(e);
		}
		
		return resp;
	}

	@Override
	public List<MedicionTO> obtenerDatosRango(VistaParaGestionTO peticion) {
		List<MedicionTO> resp = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		/*
		 * select * from datosAcumuladosRango('C', '02','2014-09-01 00:00:00', '2014-09-03 00:00:00' );
		   el id del edificio corresponde a su numeracion sin cliente, no 102, sino 02
		 * */
		String query = "SELECT fecha, valor_medicion, id_sensor " +
					   " FROM datosAcumuladosRango(?, ?,?, ? );";
		
		try {
			pstmt = this.conn.prepareStatement(query);
			
			pstmt.setString(1,peticion.getIdConsumo());
			pstmt.setString(2,peticion.getEdificio());
			pstmt.setTimestamp(3,peticion.getFechaInicio());
			pstmt.setTimestamp(4,peticion.getFechaFin());
			
			resp = new ArrayList<MedicionTO>();
			rs = pstmt.executeQuery();
			
			while(rs.next())
			{
				
				MedicionTO m =  new MedicionTO();
				m.setFechaMedicion(rs.getTimestamp(1));
				m.setMedicion(rs.getDouble(2));
				m.setIdTipoConsumo(rs.getString(3));
				
				
				m.getMediciones().add(rs.getDouble(2));
				m.getMediciones().add(35.2);
				resp.add(m);
			}
			
			
		} catch (SQLException sqle){
			UtilLog.registrar(sqle);
		}
		catch (Exception e) {
			UtilLog.registrar(e);
		}
			// TODO: handle exception
		
		
		
		return resp;
	}

	@Override
	public double totalMedicionHoy(String idMedicion, int idEdificio) {
		double resp = 0;
		PreparedStatement pstmt = null;
		String query = "SELECT CONSUMO_MEDICION_DIA( ? , ? );";
		ResultSet rs = null;
		try {
			pstmt = this.conn.prepareStatement(query);
			
			pstmt.setString(1, idMedicion);
			pstmt.setInt(2, idEdificio);
			
			
			rs = pstmt.executeQuery();
			if(rs.next())
				resp = rs.getDouble(1);
			
			
			resp = (resp>0) ? resp : 0;
			
			rs.close();
			pstmt.close();
			
		}
		catch(SQLException esql){
			UtilLog.registrar(esql);
		}
		catch (Exception e) {
			UtilLog.registrar(e);
		}
		
		return resp;
	}
	/////VISTAS PARA DETALLE
	//1
	@Override
	public List<MedicionTO> obtenerDatosMedicionHoyPath(String idMedicion,	int idEdificio ,  int idPiso , int idZona , int minutos) {
		List<MedicionTO> resp = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		String query = "SELECT m.fecha, m.valor_medicion, t.unidad_medicion " +
					   "FROM medicionesUltimas24HorasPath( ? , ? , ?  , ? , ?  )  m "+
					   "INNER JOIN tipo_consumo_sensor t on t.id_tipo_medicion = m.id_medicion;";
	 
		
		try {
			pstmt = this.conn.prepareStatement(query);
			pstmt.setString(1,idMedicion);
			pstmt.setString(2,CalculosUtil.fomatId(idEdificio));
			pstmt.setString(3,CalculosUtil.fomatId(idPiso));
			pstmt.setString(4,CalculosUtil.fomatId(idZona));
			pstmt.setInt(5,minutos);
			
			rs = pstmt.executeQuery();
			resp = new ArrayList<MedicionTO>();
			while(rs.next()){
				MedicionTO m = new MedicionTO();
				//				
				m.setFechaMedicion(rs.getTimestamp(1));
				m.setMedicion(rs.getDouble(2));
				m.setUnidadMedicion(rs.getString(3));
				//				
				resp.add(m);
			}
			
			pstmt.close();
			rs.close();
		}catch (SQLException sqle) {
				UtilLog.registrar(sqle);
		}catch (Exception e) {
			UtilLog.registrar(e);
		}
		
		
		return resp;
	}
	//2
	public List<MedicionTO> obtenerDatosMedicionHoyPathConsumo(String idMedicion,	String idConsumo, int idEdificio ,  int idPiso , int idZona , int minutos) {
		List<MedicionTO> resp = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		String query = "SELECT m.fecha, m.valor_medicion, t.unidad_medicion " +
					   "FROM medicionesUltimas24HorasPath( ? , ?,  ? , ?  , ? , ?  ) m "+
					   "INNER JOIN tipo_consumo_sensor t on t.id_tipo_medicion = m.id_medicion";
		
  
	
		try {
			pstmt = this.conn.prepareStatement(query);
			pstmt.setString(1,idMedicion);
			pstmt.setString(2,idConsumo);
			pstmt.setString(3,CalculosUtil.fomatId(idEdificio));
			pstmt.setString(4,CalculosUtil.fomatId(idPiso));
			pstmt.setString(5,CalculosUtil.fomatId(idZona));
			pstmt.setInt(6,minutos);
			
			rs = pstmt.executeQuery();
			resp = new ArrayList<MedicionTO>();
			while(rs.next()){
				MedicionTO m = new MedicionTO();
				//				
				m.setFechaMedicion(rs.getTimestamp(1));
				m.setMedicion(rs.getDouble(2));
				m.setUnidadMedicion(rs.getString(3));
				//				
				resp.add(m);
			}
			
			pstmt.close();
			rs.close();
		}catch (SQLException sqle) {
				UtilLog.registrar(sqle);
		}catch (Exception e) {
			UtilLog.registrar(e);
		}
		
		
		return resp;
	}
	//3
	public List<MedicionTO> obtenerDatosMedicionHoySensor(String idMedicion,	int idEdificio , String idSensor , int minutos) {
		List<MedicionTO> resp = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		String query = "SELECT  m.fecha, m.valor_medicion, t.unidad_medicion  " +
					   "FROM medicionesUltimas24HorasSensor( ? , ? , ?  , ?  ) m "+
					   "INNER JOIN tipo_consumo_sensor t on t.id_tipo_medicion = m.id_medicion";
		
  

		try {
			pstmt = this.conn.prepareStatement(query);
			pstmt.setString(1,idMedicion);
			pstmt.setString(2,CalculosUtil.fomatId(idEdificio));
			pstmt.setString(3, idSensor);
			pstmt.setInt(5,minutos);
			
			rs = pstmt.executeQuery();
			resp = new ArrayList<MedicionTO>();
			while(rs.next()){
				MedicionTO m = new MedicionTO();
				//				
				m.setFechaMedicion(rs.getTimestamp(1));
				m.setMedicion(rs.getDouble(2));
				m.setUnidadMedicion(rs.getString(3));
				//				
				resp.add(m);
			}
			
			pstmt.close();
			rs.close();
		}catch (SQLException sqle) {
				UtilLog.registrar(sqle);
		}catch (Exception e) {
			UtilLog.registrar(e);
		}
		
		
		return resp;
	}
	//4
	public List<MedicionTO> obtenerDatosMedicionHoySensorConsumo(String idMedicion, String idConsumo ,	int idEdificio ,  String idSensor , int minutos) {
		List<MedicionTO> resp = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		String query = "SELECT m.fecha, m.valor_medicion, t.unidad_medicion " +
					   "FROM medicionesUltimas24HorasSensor ( ? , ? , ?  , ? , ?  ) m " +
					   "INNER JOIN tipo_consumo_sensor t on t.id_tipo_medicion = m.id_medicion";
		
  
		
		try {
			pstmt = this.conn.prepareStatement(query);
			pstmt.setString(1,idMedicion);
			pstmt.setString(2,idConsumo);
			pstmt.setString(3,CalculosUtil.fomatId(idEdificio));
			pstmt.setString(4,idSensor);
			pstmt.setInt(5,minutos);
			
			rs = pstmt.executeQuery();
			resp = new ArrayList<MedicionTO>();
			while(rs.next()){
				MedicionTO m = new MedicionTO();
				//				
				m.setFechaMedicion(rs.getTimestamp(1));
				m.setMedicion(rs.getDouble(2));
				m.setUnidadMedicion(rs.getString(3));
				//				
				resp.add(m);
			}
			
			pstmt.close();
			rs.close();
		}catch (SQLException sqle) {
				UtilLog.registrar(sqle);
		}catch (Exception e) {
			UtilLog.registrar(e);
		}
		
		
		return resp;
	}
	public List<MedicionTO> obtenerDatosMedicionHoy_porConsumo(String idMedicion, String idConsumo,int idEdificio,  int idPiso , int idZona , int idSensor , int minutos) {
		List<MedicionTO> resp = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		String query = "SELECT fecha, valor_medicion " +
		"FROM medicionesUltimas24Horas ( ? , ? , ? , ? , ? , ?)";
		 
		
		
		try {
			pstmt = this.conn.prepareStatement(query);
			pstmt.setString(1,idMedicion);
			pstmt.setString(2,idConsumo);
			pstmt.setString(3,CalculosUtil.fomatId(idEdificio));
			pstmt.setString(4,CalculosUtil.fomatId(idPiso));
			pstmt.setString(5,CalculosUtil.fomatId(idZona));
			pstmt.setString(6,CalculosUtil.fomatId(minutos));
			rs = pstmt.executeQuery();
			resp = new ArrayList<MedicionTO>();
			while(rs.next()){
				MedicionTO m = new MedicionTO();
				//				
				m.setFechaMedicion(rs.getTimestamp(1));
				m.setMedicion(rs.getDouble(2));
				//				
				resp.add(m);
			}
			
			pstmt.close();
			rs.close();
		}catch (SQLException sqle) {
			UtilLog.registrar(sqle);
		}catch (Exception e) {
			UtilLog.registrar(e);
		}
		
		
		return resp;
	}



	@Override
	public List<MedicionTO> totalConsumos(String idMedicion, int idEdificio ,  int idPiso, int idZona , String idSensor, String periodo) {
		List<MedicionTO> resp = null;
		List<TipoMedicionConsumoSensorTO> consumos = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		consumos = obtenerConsumos(idMedicion, this.conn); // si no llamar al service para generar otra conexion
		
		
		String query = "SELECT medicion, idConsumo FROM totalConsumos( ? , ? , ? , ? , ? );";
		 
		
		try {
		 
			resp = new ArrayList<MedicionTO>();
			//for(TipoMedicionConsumoSensorTO consumo : consumos){
				pstmt = this.conn.prepareStatement(query);
				pstmt.setString(1, idMedicion);
				pstmt.setString(2,  CalculosUtil.fomatId(idEdificio));
				pstmt.setString(3,  CalculosUtil.fomatId(idPiso));
				pstmt.setString(4,  CalculosUtil.fomatId(idZona));
				pstmt.setString(5, periodo);
				rs = pstmt.executeQuery();
				
				while(rs.next()){
					MedicionTO m = new MedicionTO();
					//				
					//m.setDescripcionMedicion(consumo.getNombreTipoMedicion());
					m.setMedicion(rs.getDouble(1));
					m.setIdTipoConsumo(rs.getString(2));
					m.setIdTipoMedicion(idMedicion);
					//				
					resp.add(m);
				}
			//}
				boolean E = false;
				for(TipoMedicionConsumoSensorTO consumo : consumos){
					E = false;
					for(MedicionTO m : resp){
						if(consumo.getCodigoTipoMedicion().equalsIgnoreCase(m.getIdTipoConsumo())){
							m.setDescripcionMedicion(consumo.getNombreTipoMedicion());
							E=true;
						}
					}
					if(!E){
						MedicionTO newM = new MedicionTO();
						newM.setMedicion(0);
						newM.setDescripcionMedicion(consumo.getNombreTipoMedicion());
						newM.setIdTipoConsumo(consumo.getCodigoTipoMedicion());
						newM.setIdTipoMedicion(idMedicion);
					}
						
				}

			
			pstmt.close();
			rs.close();
		}catch (SQLException sqle) {
			UtilLog.registrar(sqle);
		}catch (Exception e) {
			UtilLog.registrar(e);
		}
		
		
		return resp;
	}
	
	private List<TipoMedicionConsumoSensorTO> obtenerConsumos(String idMedicion, Connection c){
		List<TipoMedicionConsumoSensorTO> resp = null;
		
		FacadeSensor fsensor = new FacadeSensor();
		resp = fsensor.obtenerTipoDeConsumo(idMedicion, c);
		return resp;
		
	}
/*
 *   valor_medicion real,
  id_sensor character varying(13),
  valor_medicion_promedio real,
  fecha_hora timestamp without time zone
 * */
	@Override
	public List<MedicionTO> obtenerAlertas(int idEdificio) {
		List<MedicionTO> resp = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
	
		
		String query = "SELECT id_sensor , valor_medicion, valor_medicion_promedio ,  fecha_hora FROM ALERTA";
		
		
		String id_string = Integer.toString(idEdificio);
		if(id_string.length()==1)
			id_string = "0"+id_string;
 
		
		
		try {
		 
			resp = new ArrayList<MedicionTO>();
				pstmt = this.conn.prepareStatement(query);
	
				rs = pstmt.executeQuery();
				
				while(rs.next()){
					MedicionTO m = new MedicionTO();
					//				
					//m.setDescripcionMedicion(consumo.getNombreTipoMedicion());
					m.setAlerta(true);
					m.setIdSensor(rs.getString(1));
					m.setMedicion(rs.getDouble(2));
					m.setPromedioMedicion(rs.getDouble(3));
					m.setFechaMedicion(rs.getTimestamp(4));
					//				
					resp.add(m);
				}
		
			pstmt.close();
			rs.close();
		}catch (SQLException sqle) {
			UtilLog.registrar(sqle);
		}catch (Exception e) {
			UtilLog.registrar(e);
		}
		
		
		return resp;
	}
 
}
